using System;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace RunAllTestsInSolutionTask
{
    internal class SolutionParser
    {
        private static string _SolutionPath;

        public static IList<string> GetAllTestDlls(string slnfileName,string configuration)
        {
            if (!File.Exists(slnfileName))
                throw new ArgumentException("Sln File Not Found:" +slnfileName);
            _SolutionPath = Path.GetDirectoryName(slnfileName); 
            var solutionXml = Load(slnfileName);
            var projectFileNames = GetAllProjectsFiles(solutionXml);
            var dllFiles = GetTestdllsFromProjectFiles(projectFileNames,configuration);
            return dllFiles;
        }

        public static IList<string> GetAllTestDlls(string slnFileName, string configuration, string excludedList)
        {
            if (!File.Exists(slnFileName))
                throw new ArgumentException("Sln File Not Found:" + slnFileName);
            _SolutionPath = Path.GetDirectoryName(slnFileName);
            var solutionXml = Load(slnFileName);
            var projectFileNames = GetAllProjectsFiles(solutionXml);
            var afterExclude = (from project in projectFileNames
                               where !(project.Contains(excludedList))
                               select project).ToList();
            var dllFiles = GetTestdllsFromProjectFiles(afterExclude, configuration);
            return dllFiles;
        }
        
        private static IList<string> GetAllProjectsFiles(IList<string> lines)
        {
            IList<string> result = new List<string>();
            
            var ans = from line in lines
                      where (line.StartsWith("Project("))
                      select line;
        
            foreach (var line in ans)
            {
                var dll = GetDllfromLine(line);
                dll = Path.Combine(_SolutionPath, dll.Trim().Trim('"'));
                result.Add(dll);
            }

            result = (from projFile in result
                      where (projFile.EndsWith(".csproj"))
                      select projFile).ToList();

            return result;
        }

        private static string GetDllfromLine(string line)
        {
            var parts = line.Split(new char[] { ',' });
            return parts[1];
        }

        private static IList<string> Load(string slnfileName)
        {
            var lines = new List<string>();
            StreamReader file = new StreamReader(slnfileName);
            while (!file.EndOfStream)
            {
                var line = file.ReadLine();
                lines.Add(line);
            }
            return lines;
        }

        private static IList<string> GetTestdllsFromProjectFiles(IList<String> projectFileNames, string configuration)
        {
            var result = new List<string>();
            foreach (String projectFileName in projectFileNames)
            {
                if (ProjectParser.IsTestProject(projectFileName))
                    result.Add(ProjectParser.GetOutputDll(projectFileName, configuration));
            }
            return result;
        }

    }
}
